home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / System.php < prev    next >
PHP Script  |  2004-10-01  |  18KB  |  541 lines

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 5                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2004 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available through the world-wide-web at the following url:           |
  11. // | http://www.php.net/license/3_0.txt.                                  |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Tomas V.V.Cox <cox@idecnet.com>                             |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: System.php,v 1.35 2004/01/19 03:32:12 cellog Exp $
  20. //
  21.  
  22. require_once 'PEAR.php';
  23. require_once 'Console/Getopt.php';
  24.  
  25. $GLOBALS['_System_temp_files'] = array();
  26.  
  27. /**
  28. * System offers cross plattform compatible system functions
  29. *
  30. * Static functions for different operations. Should work under
  31. * Unix and Windows. The names and usage has been taken from its respectively
  32. * GNU commands. The functions will return (bool) false on error and will
  33. * trigger the error with the PHP trigger_error() function (you can silence
  34. * the error by prefixing a '@' sign after the function call).
  35. *
  36. * Documentation on this class you can find in:
  37. * http://pear.php.net/manual/
  38. *
  39. * Example usage:
  40. * if (!@System::rm('-r file1 dir1')) {
  41. *    print "could not delete file1 or dir1";
  42. * }
  43. *
  44. * In case you need to to pass file names with spaces,
  45. * pass the params as an array:
  46. *
  47. * System::rm(array('-r', $file1, $dir1));
  48. *
  49. * @package  System
  50. * @author   Tomas V.V.Cox <cox@idecnet.com>
  51. * @version  $Revision: 1.35 $
  52. * @access   public
  53. * @see      http://pear.php.net/manual/
  54. */
  55. class System
  56. {
  57.     /**
  58.     * returns the commandline arguments of a function
  59.     *
  60.     * @param    string  $argv           the commandline
  61.     * @param    string  $short_options  the allowed option short-tags
  62.     * @param    string  $long_options   the allowed option long-tags
  63.     * @return   array   the given options and there values
  64.     * @access private
  65.     */
  66.     function _parseArgs($argv, $short_options, $long_options = null)
  67.     {
  68.         if (!is_array($argv) && $argv !== null) {
  69.             $argv = preg_split('/\s+/', $argv);
  70.         }
  71.         return Console_Getopt::getopt2($argv, $short_options);
  72.     }
  73.  
  74.     /**
  75.     * Output errors with PHP trigger_error(). You can silence the errors
  76.     * with prefixing a "@" sign to the function call: @System::mkdir(..);
  77.     *
  78.     * @param mixed $error a PEAR error or a string with the error message
  79.     * @return bool false
  80.     * @access private
  81.     */
  82.     function raiseError($error)
  83.     {
  84.         if (PEAR::isError($error)) {
  85.             $error = $error->getMessage();
  86.         }
  87.         trigger_error($error, E_USER_WARNING);
  88.         return false;
  89.     }
  90.  
  91.     /**
  92.     * Creates a nested array representing the structure of a directory
  93.     *
  94.     * System::_dirToStruct('dir1', 0) =>
  95.     *   Array
  96.     *    (
  97.     *    [dirs] => Array
  98.     *        (
  99.     *            [0] => dir1
  100.     *        )
  101.     *
  102.     *    [files] => Array
  103.     *        (
  104.     *            [0] => dir1/file2
  105.     *            [1] => dir1/file3
  106.     *        )
  107.     *    )
  108.     * @param    string  $sPath      Name of the directory
  109.     * @param    integer $maxinst    max. deep of the lookup
  110.     * @param    integer $aktinst    starting deep of the lookup
  111.     * @return   array   the structure of the dir
  112.     * @access   private
  113.     */
  114.  
  115.     function _dirToStruct($sPath, $maxinst, $aktinst = 0)
  116.     {
  117.         $struct = array('dirs' => array(), 'files' => array());
  118.         if (($dir = @opendir($sPath)) === false) {
  119.             System::raiseError("Could not open dir $sPath");
  120.             return $struct; // XXX could not open error
  121.         }
  122.         $struct['dirs'][] = $sPath; // XXX don't add if '.' or '..' ?
  123.         $list = array();
  124.         while ($file = readdir($dir)) {
  125.             if ($file != '.' && $file != '..') {
  126.                 $list[] = $file;
  127.             }
  128.         }
  129.         closedir($dir);
  130.         sort($list);
  131.         if ($aktinst < $maxinst || $maxinst == 0) {
  132.             foreach($list as $val) {
  133.                 $path = $sPath . DIRECTORY_SEPARATOR . $val;
  134.                 if (is_dir($path)) {
  135.                     $tmp = System::_dirToStruct($path, $maxinst, $aktinst+1);
  136.                     $struct = array_merge_recursive($tmp, $struct);
  137.                 } else {
  138.                     $struct['files'][] = $path;
  139.                 }
  140.             }
  141.         }
  142.         return $struct;
  143.     }
  144.  
  145.     /**
  146.     * Creates a nested array representing the structure of a directory and files
  147.     *
  148.     * @param    array $files Array listing files and dirs
  149.     * @return   array
  150.     * @see System::_dirToStruct()
  151.     */
  152.     function _multipleToStruct($files)
  153.     {
  154.         $struct = array('dirs' => array(), 'files' => array());
  155.         settype($files, 'array');
  156.         foreach ($files as $file) {
  157.             if (is_dir($file)) {
  158.                 $tmp = System::_dirToStruct($file, 0);
  159.                 $struct = array_merge_recursive($tmp, $struct);
  160.             } else {
  161.                 $struct['files'][] = $file;
  162.             }
  163.         }
  164.         return $struct;
  165.     }
  166.  
  167.     /**
  168.     * The rm command for removing files.
  169.     * Supports multiple files and dirs and also recursive deletes
  170.     *
  171.     * @param    string  $args   the arguments for rm
  172.     * @return   mixed   PEAR_Error or true for success
  173.     * @access   public
  174.     */
  175.     function rm($args)
  176.     {
  177.         $opts = System::_parseArgs($args, 'rf'); // "f" do nothing but like it :-)
  178.         if (PEAR::isError($opts)) {
  179.             return System::raiseError($opts);
  180.         }
  181.         foreach($opts[0] as $opt) {
  182.             if ($opt[0] == 'r') {
  183.                 $do_recursive = true;
  184.             }
  185.         }
  186.         $ret = true;
  187.         if (isset($do_recursive)) {
  188.             $struct = System::_multipleToStruct($opts[1]);
  189.             foreach($struct['files'] as $file) {
  190.                 if (!@unlink($file)) {
  191.                     $ret = false;
  192.                 }
  193.             }
  194.             foreach($struct['dirs'] as $dir) {
  195.                 if (!@rmdir($dir)) {
  196.                     $ret = false;
  197.                 }
  198.             }
  199.         } else {
  200.             foreach ($opts[1] as $file) {
  201.                 $delete = (is_dir($file)) ? 'rmdir' : 'unlink';
  202.                 if (!@$delete($file)) {
  203.                     $ret = false;
  204.                 }
  205.             }
  206.         }
  207.         return $ret;
  208.     }
  209.  
  210.     /**
  211.     * Make directories. Note that we use call_user_func('mkdir') to avoid
  212.     * a problem with ZE2 calling System::mkDir instead of the native PHP func.
  213.     *
  214.     * @param    string  $args    the name of the director(y|ies) to create
  215.     * @return   bool    True for success
  216.     * @access   public
  217.     */
  218.     function mkDir($args)
  219.     {
  220.         $opts = System::_parseArgs($args, 'pm:');
  221.         if (PEAR::isError($opts)) {
  222.             return System::raiseError($opts);
  223.         }
  224.         $mode = 0777; // default mode
  225.         foreach($opts[0] as $opt) {
  226.             if ($opt[0] == 'p') {
  227.                 $create_parents = true;
  228.             } elseif($opt[0] == 'm') {
  229.                 // if the mode is clearly an octal number (starts with 0)
  230.                 // convert it to decimal
  231.                 if (strlen($opt[1]) && $opt[1]{0} == '0') {
  232.                     $opt[1] = octdec($opt[1]);
  233.                 } else {
  234.                     // convert to int
  235.                     $opt[1] += 0;
  236.                 }
  237.                 $mode = $opt[1];
  238.             }
  239.         }
  240.         $ret = true;
  241.         if (isset($create_parents)) {
  242.             foreach($opts[1] as $dir) {
  243.                 $dirstack = array();
  244.                 while (!@is_dir($dir) && $dir != DIRECTORY_SEPARATOR) {
  245.                     array_unshift($dirstack, $dir);
  246.                     $dir = dirname($dir);
  247.                 }
  248.                 while ($newdir = array_shift($dirstack)) {
  249.                     if (!call_user_func('mkdir', $newdir, $mode)) {
  250.                         $ret = false;
  251.                     }
  252.                 }
  253.             }
  254.         } else {
  255.             foreach($opts[1] as $dir) {
  256.                 if (!@is_dir($dir) && !call_user_func('mkdir', $dir, $mode)) {
  257.                     $ret = false;
  258.                 }
  259.             }
  260.         }
  261.         return $ret;
  262.     }
  263.  
  264.     /**
  265.     * Concatenate files
  266.     *
  267.     * Usage:
  268.     * 1) $var = System::cat('sample.txt test.txt');
  269.     * 2) System::cat('sample.txt test.txt > final.txt');
  270.     * 3) System::cat('sample.txt test.txt >> final.txt');
  271.     *
  272.     * Note: as the class use fopen, urls should work also (test that)
  273.     *
  274.     * @param    string  $args   the arguments
  275.     * @return   boolean true on success
  276.     * @access   public
  277.     */
  278.     function &cat($args)
  279.     {
  280.         $ret = null;
  281.         $files = array();
  282.         if (!is_array($args)) {
  283.             $args = preg_split('/\s+/', $args);
  284.         }
  285.         for($i=0; $i < count($args); $i++) {
  286.             if ($args[$i] == '>') {
  287.                 $mode = 'wb';
  288.                 $outputfile = $args[$i+1];
  289.                 break;
  290.             } elseif ($args[$i] == '>>') {
  291.                 $mode = 'ab+';
  292.                 $outputfile = $args[$i+1];
  293.                 break;
  294.             } else {
  295.                 $files[] = $args[$i];
  296.             }
  297.         }
  298.         if (isset($mode)) {
  299.             if (!$outputfd = fopen($outputfile, $mode)) {
  300.                 $err = System::raiseError("Could not open $outputfile");
  301.                 return $err;
  302.             }
  303.             $ret = true;
  304.         }
  305.         foreach ($files as $file) {
  306.             if (!$fd = fopen($file, 'r')) {
  307.                 System::raiseError("Could not open $file");
  308.                 continue;
  309.             }
  310.             while ($cont = fread($fd, 2048)) {
  311.                 if (isset($outputfd)) {
  312.                     fwrite($outputfd, $cont);
  313.                 } else {
  314.                     $ret .= $cont;
  315.                 }
  316.             }
  317.             fclose($fd);
  318.         }
  319.         if (@is_resource($outputfd)) {
  320.             fclose($outputfd);
  321.         }
  322.         return $ret;
  323.     }
  324.  
  325.     /**
  326.     * Creates temporary files or directories. This function will remove
  327.     * the created files when the scripts finish its execution.
  328.     *
  329.     * Usage:
  330.     *   1) $tempfile = System::mktemp("prefix");
  331.     *   2) $tempdir  = System::mktemp("-d prefix");
  332.     *   3) $tempfile = System::mktemp();
  333.     *   4) $tempfile = System::mktemp("-t /var/tmp prefix");
  334.     *
  335.     * prefix -> The string that will be prepended to the temp name
  336.     *           (defaults to "tmp").
  337.     * -d     -> A temporary dir will be created instead of a file.
  338.     * -t     -> The target dir where the temporary (file|dir) will be created. If
  339.     *           this param is missing by default the env vars TMP on Windows or
  340.     *           TMPDIR in Unix will be used. If these vars are also missing
  341.     *           c:\windows\temp or /tmp will be used.
  342.     *
  343.     * @param   string  $args  The arguments
  344.     * @return  mixed   the full path of the created (file|dir) or false
  345.     * @see System::tmpdir()
  346.     * @access  public
  347.     */
  348.     function mktemp($args = null)
  349.     {
  350.         static $first_time = true;
  351.         $opts = System::_parseArgs($args, 't:d');
  352.         if (PEAR::isError($opts)) {
  353.             return System::raiseError($opts);
  354.         }
  355.         foreach($opts[0] as $opt) {
  356.             if($opt[0] == 'd') {
  357.                 $tmp_is_dir = true;
  358.             } elseif($opt[0] == 't') {
  359.                 $tmpdir = $opt[1];
  360.             }
  361.         }
  362.         $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp';
  363.         if (!isset($tmpdir)) {
  364.             $tmpdir = System::tmpdir();
  365.         }
  366.         if (!System::mkDir("-p $tmpdir")) {
  367.             return false;
  368.         }
  369.         $tmp = tempnam($tmpdir, $prefix);
  370.         if (isset($tmp_is_dir)) {
  371.             unlink($tmp); // be careful possible race condition here
  372.             if (!call_user_func('mkdir', $tmp, 0700)) {
  373.                 return System::raiseError("Unable to create temporary directory $tmpdir");
  374.             }
  375.         }
  376.         $GLOBALS['_System_temp_files'][] = $tmp;
  377.         if ($first_time) {
  378.             PEAR::registerShutdownFunc(array('System', '_removeTmpFiles'));
  379.             $first_time = false;
  380.         }
  381.         return $tmp;
  382.     }
  383.  
  384.     /**
  385.     * Remove temporary files created my mkTemp. This function is executed
  386.     * at script shutdown time
  387.     *
  388.     * @access private
  389.     */
  390.     function _removeTmpFiles()
  391.     {
  392.         if (count($GLOBALS['_System_temp_files'])) {
  393.             $delete = $GLOBALS['_System_temp_files'];
  394.             array_unshift($delete, '-r');
  395.             System::rm($delete);
  396.         }
  397.     }
  398.  
  399.     /**
  400.     * Get the path of the temporal directory set in the system
  401.     * by looking in its environments variables.
  402.     * Note: php.ini-recommended removes the "E" from the variables_order setting,
  403.     * making unavaible the $_ENV array, that s why we do tests with _ENV
  404.     *
  405.     * @return string The temporal directory on the system
  406.     */
  407.     function tmpdir()
  408.     {
  409.         if (OS_WINDOWS) {
  410.             if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) {
  411.                 return $var;
  412.             }
  413.             if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) {
  414.                 return $var;
  415.             }
  416.             if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) {
  417.                 return $var;
  418.             }
  419.             return getenv('SystemRoot') . '\temp';
  420.         }
  421.         if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) {
  422.             return $var;
  423.         }
  424.         return '/tmp';
  425.     }
  426.  
  427.     /**
  428.     * The "which" command (show the full path of a command)
  429.     *
  430.     * @param string $program The command to search for
  431.     * @return mixed A string with the full path or false if not found
  432.     * @author Stig Bakken <ssb@php.net>
  433.     */
  434.     function which($program, $fallback = false)
  435.     {
  436.         // is_executable() is not available on windows
  437.         if (OS_WINDOWS) {
  438.             $pear_is_executable = 'is_file';
  439.         } else {
  440.             $pear_is_executable = 'is_executable';
  441.         }
  442.  
  443.         // full path given
  444.         if (basename($program) != $program) {
  445.             return (@$pear_is_executable($program)) ? $program : $fallback;
  446.         }
  447.  
  448.         // XXX FIXME honor safe mode
  449.         $path_delim = OS_WINDOWS ? ';' : ':';
  450.         $exe_suffixes = OS_WINDOWS ? array('.exe','.bat','.cmd','.com') : array('');
  451.         $path_elements = explode($path_delim, getenv('PATH'));
  452.         foreach ($exe_suffixes as $suff) {
  453.             foreach ($path_elements as $dir) {
  454.                 $file = $dir . DIRECTORY_SEPARATOR . $program . $suff;
  455.                 if (@is_file($file) && @$pear_is_executable($file)) {
  456.                     return $file;
  457.                 }
  458.             }
  459.         }
  460.         return $fallback;
  461.     }
  462.  
  463.     /**
  464.     * The "find" command
  465.     *
  466.     * Usage:
  467.     *
  468.     * System::find($dir);
  469.     * System::find("$dir -type d");
  470.     * System::find("$dir -type f");
  471.     * System::find("$dir -name *.php");
  472.     * System::find("$dir -name *.php -name *.htm*");
  473.     * System::find("$dir -maxdepth 1");
  474.     *
  475.     * Params implmented:
  476.     * $dir            -> Start the search at this directory
  477.     * -type d         -> return only directories
  478.     * -type f         -> return only files
  479.     * -maxdepth <n>   -> max depth of recursion
  480.     * -name <pattern> -> search pattern (bash style). Multiple -name param allowed
  481.     *
  482.     * @param  mixed Either array or string with the command line
  483.     * @return array Array of found files
  484.     *
  485.     */
  486.     function find($args)
  487.     {
  488.         if (!is_array($args)) {
  489.             $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
  490.         }
  491.         $dir = array_shift($args);
  492.         $patterns = array();
  493.         $depth = 0;
  494.         $do_files = $do_dirs = true;
  495.         for ($i = 0; $i < count($args); $i++) {
  496.             switch ($args[$i]) {
  497.                 case '-type':
  498.                     if (in_array($args[$i+1], array('d', 'f'))) {
  499.                         if ($args[$i+1] == 'd') {
  500.                              $do_files = false;
  501.                         } else {
  502.                             $do_dirs = false;
  503.                         }
  504.                     }
  505.                     $i++;
  506.                     break;
  507.                 case '-name':
  508.                     $patterns[] = "(" . preg_replace(array('/\./', '/\*/'),
  509.                                                      array('\.', '.*'),
  510.                                                      $args[$i+1])
  511.                                       . ")";
  512.                     $i++;
  513.                     break;
  514.                 case '-maxdepth':
  515.                     $depth = $args[$i+1];
  516.                     break;
  517.             }
  518.         }
  519.         $path = System::_dirToStruct($dir, $depth);
  520.         if ($do_files && $do_dirs) {
  521.             $files = array_merge($path['files'], $path['dirs']);
  522.         } elseif ($do_dirs) {
  523.             $files = $path['dirs'];
  524.         } else {
  525.             $files = $path['files'];
  526.         }
  527.         if (count($patterns)) {
  528.             $patterns = implode('|', $patterns);
  529.             $ret = array();
  530.             for ($i = 0; $i < count($files); $i++) {
  531.                 if (preg_match("#^$patterns\$#", $files[$i])) {
  532.                     $ret[] = $files[$i];
  533.                 }
  534.             }
  535.             return $ret;
  536.         }
  537.         return $files;
  538.     }
  539. }
  540. ?>
  541.